﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace EaWebService
{
    /// <summary>
    /// Summary description for Service1
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class Service1 : System.Web.Services.WebService
    {

        private static int[] currentlyBestSolution;


        //Method for call EA
        [WebMethod]
        public int[] callEA(int[][] maze, int mazeDimension, int exitX, int exitY, int startX, int startY,
                    int chromosomeLength, int populationSize, string mutationType, string selectionType, string crossoverType,
                    string fitnessScaleType, double probability, double boltzmannTemp)
        {
            Generation g = new Generation(maze, mazeDimension, exitX, exitY, startX, startY, chromosomeLength,
                populationSize, mutationType, selectionType, crossoverType, fitnessScaleType, probability,
                boltzmannTemp);

            currentlyBestSolution = new int[chromosomeLength];

            while (g.Solution == null)
            {
                g.Epoch();
                currentlyBestSolution = g.getBestPath();
            }
            return g.Solution;
        }

        [WebMethod]
        public int[] getBestFitted()
        {
            return currentlyBestSolution;
        }
        
        
        
        //For paralelization
        [WebMethod]
        public int[] callEAParalel(int[][] maze, int mazeDimension, int exitX, int exitY, int startX, int startY,
            int chromosomeLength, int populationSize, string mutationType, string selectionType, string crossoverType,
            string fitnessScaleType, double probability, double boltzmannTemp)
        {
            List<int> lista = new List<int>();
            int posx = -1;
            int posy = -1;

            int[] solution = null;

            uniquePairXAxis(ref posx, ref  posy, maze, mazeDimension);
            if (posx != -1 && posy != -1)
            {
                int[][] mazeUp = new int[posy + 1][];
                int[][] mazeDown = new int[mazeDimension - posy - 1][];

                for (int i = 0; i < posy + 1; i++)
                {
                    mazeUp[i] = new int[mazeDimension];
                    for (int j = 0; j < mazeDimension; j++)
                        mazeUp[i][j] = maze[i][j];
                }

                for (int i = 0; i < mazeDimension - posy - 1; i++)
                {
                    mazeDown[i] = new int[mazeDimension];
                    for (int j = 0; j < mazeDimension; j++)
                        mazeDown[i][j] = maze[i + posy + 1][j];
                }

                //Call callEA( for mazeUp) and get pathUp
                //Call callEA( for mazeDown) and get pathDown

                //Merge pathUp and pathDown into solution
                return solution;
            }


            uniquePairYAxis(ref posx, ref  posy, maze, mazeDimension);
            if (posx != -1 && posy != -1)
            {
                int[][] mazeLeft = new int[mazeDimension][];
                int[][] mazeRight = new int[mazeDimension][];

                for (int i = 0; i < mazeDimension; i++)
                {
                    mazeLeft[i] = new int[posy + 1];
                    for (int j = 0; j < posy + 1; j++)
                        mazeLeft[i][j] = maze[i][j];
                }

                for (int i = 0; i < mazeDimension; i++)
                {
                    mazeRight[i] = new int[mazeDimension - posx - 1];
                    for (int j = 0; j < mazeDimension - posx - 1; j++)
                        mazeRight[i][j] = maze[i][j + posx + 1];
                }

                //Call callEA( for mazeUp) and get pathLeft
                //Call callEA( for mazeDown) and get pathRight

                //Merge pathLeft and pathRight into solution
                return solution;
            }



            return callEA(maze, mazeDimension, exitX, exitY, startX, startY, chromosomeLength, populationSize, mutationType,
                selectionType, crossoverType, fitnessScaleType, probability, boltzmannTemp);

        }


        private static void uniquePairYAxis(ref int posx, ref int posy, int[][] maze, int mazeDimension)
        {
            List<int> lista = new List<int>();

            for (int k = 0; k < mazeDimension - 1; k++)
            {

                for (int i = 0; i < mazeDimension; i++)
                    if (maze[i][k] == 0 && maze[i][k + 1] == 0)
                    {
                        lista.Add(i);
                        posy = i;
                        posx = k;

                        if (lista.Count > 1)
                        {
                            lista.Clear();
                            posy = -1;
                            posx = -1;
                            break;
                        }
                    }

                if (lista.Count == 1)
                    break;
            }
        }


        private static void uniquePairXAxis(ref int posx, ref int posy, int[][] maze, int mazeDimension)
        {
            List<int> lista = new List<int>();

            for (int k = 0; k < mazeDimension - 1; k++)
            {
                for (int i = 0; i < mazeDimension; i++)
                    if (maze[k][i] == 0 && maze[k + 1][i] == 0)
                    {
                        lista.Add(i);
                        posx = i;
                        posy = k;

                        if (lista.Count > 1)
                        {
                            lista.Clear();
                            posy = -1;
                            posx = -1;
                            break;
                        }
                    }

                if (lista.Count == 1)
                    break;
            }
        }

       
    }
}